package com.corpgovernment.common.requestprocess;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import lombok.extern.slf4j.Slf4j;

/**
 * 异步任务工具
 *
 * @author dlz
 * @since 2023/4/26
 */
@Slf4j
public final class AsyncTaskUtil {
    private AsyncTaskUtil() {}

    /**
     * 等待所有任务执行完成并获取结果
     *
     * @param tasks 所有任务
     * @param timeout 超时时间
     * @param timeUnit 超时时间单位
     */
    public static <T> List<T> getAllResultIgnoreException(List<Future<T>> tasks, int timeout, TimeUnit timeUnit) {
        return getAllResult(tasks, timeout, timeUnit, true);
    }

    /**
     * 等待所有任务执行完成并获取结果或抛出异常
     *
     * @param tasks 所有任务
     * @param timeout 超时时间
     * @param timeUnit 超时时间单位
     */
    public static <T> List<T> getAllResultOrThrow(List<Future<T>> tasks, int timeout, TimeUnit timeUnit) {
        return getAllResult(tasks, timeout, timeUnit, false);
    }

    /**
     * 等待所有任务执行完成并获取结果
     *
     * @param tasks 所有任务
     * @param timeout 超时时间
     * @param timeUnit 超时时间单位
     */
    private static <T> List<T> getAllResult(List<Future<T>> tasks, int timeout, TimeUnit timeUnit,
        boolean ignoreException) {

        // 等待任务结束时间
        long deadline = System.currentTimeMillis() + timeUnit.toMillis(timeout);
        List<T> results = new ArrayList<>(tasks.size());
        for (Future<T> task : tasks) {
            try {
                // 需要等待的毫秒数Future
                long waitMillis = deadline - System.currentTimeMillis();
                results.add(task.get(waitMillis, TimeUnit.MILLISECONDS));
            } catch (TimeoutException oe) {
                log.error("get Future Result Error", oe);
                throw new RuntimeException("异步任务执行超时");
            } catch (InterruptedException | ExecutionException ex) {
                log.error("get Future Result Error", ex);
                throw new RuntimeException("异步任务执行异常");
            }
        }
        return results;
    }

    /**
     * 等待所有任务执行完成或抛出异常
     *
     * @param tasks 所有任务
     * @param timeout 超时时间
     * @param timeUnit 超时时间单位
     */
    public static void waitAllThrow(List<Future<?>> tasks, int timeout, TimeUnit timeUnit) {
        // 等待任务结束时间
        long deadline = System.currentTimeMillis() + timeUnit.toMillis(timeout);
        for (Future<?> task : tasks) {
            try {
                // 需要等待的毫秒数Future
                long waitMillis = deadline - System.currentTimeMillis();
                task.get(waitMillis, TimeUnit.MILLISECONDS);
            } catch (TimeoutException oe) {
                log.error("get Future Result Error", oe);
                throw new RuntimeException("异步任务执行超时");
            } catch (InterruptedException | ExecutionException ex) {
                log.error("get Future Result Error", ex);
                throw new RuntimeException("异步任务执行异常");
            }
        }
    }
}
